5장. (part1) 변하지 않는 것은 없다

  1. 5장. (part1) 변하지 않는 것은 없다
    1. 1. 우리의 디자인을 시험해 봅시다.
    2. UML 컨닝 페이퍼

1. 우리의 디자인을 시험해 봅시다.

  • 분석과 설계를 잘하면 재사용성과 확장성이 좋은 소프트웨어를 만들 수 있다.

1.1 릭의 기타 검색 도구에서 만돌린도 검색가능하도록 수정해보자.

  • 릭의 기타 검색 프로그램의 클래스 다이어그램 완성본이다.
  • 릭의 검색 도구로 만돌린도 검색할 수 있게 하세요.

1.2 추상 부모 클래스라는 것을 알고있나요?

추상클래스는 실제 구현 클래스를 위한 저장장소입니다.
추상클래스는 기능(behavior)을 정의하고, 그 기능을 서브클래스가 구현합니다..

  • Instrument는 추상 클래스이다.
    객체를 생성할 수 없다.
    Mandolin이나 Guitar 같은 Instrument의 서브 클래스를 정의해야 ?나.
    실제 구현 클래스들을 위해 존재하는 일반적인(generic)클래스 이다.

1.3 릭의 새 프로그램

*두개 이상의 클래스에서 공통된 행동(기능)을 발견할때마다, 그 행동을 하나의 클래스로 추상화하여 그 행동(기능)을 재사용하도록 하세요.

UML 컨닝 페이퍼

JAVA 부르기UML 부르기UML 나타내기
관계(relationship)연관(association)
상속(inheritance)일반화(generalization)
집합(aggregation)집합(aggregation)

1.4 릭의 새로운 검색도구를 코드로 작성하자.

Instrument.javaGuitar.java / Mandolin.java
{code}
public abstract class Instrument {
//===============================================================================================
// 객체생성
//






















---
private String SerialNumber;
private double price;
private InstrumentSpec spec;;;
//===============================================================================================

public Instrument (String serialNumber, double price, InstrumentSpec) {
//
























---
this.serialNumber = serialNumber;
this.price = price;
this.spec = spec;
//






















---
}

public InstrumentSpec getSpec() {
return spec;;
}
}

|

public class Guitar extends Instrument {
public Guitar(String serialNumber, double price, GuitarSpec spec) {
super(serialNumber, price, spec);
}}



public class Mandolin extends Instrument {
public Guitar(String serialNumber, double price, GuitarSpec spec) {
super(serialNumber, price, spec);
}
}


|

||악기 사양에 대한 추상 클래스||
|

public abstrct class InstrumentSpec {
//===============================================================================================
// 객체생성
//
























---
private Builder builder;
private String medel;
private Type type;
private Wood backWood;
private Wood topWood;
//===============================================================================================

/**

  • 악기에 대한 속성을 받는다.
  • @throws Exception
    */
    public InstrumentSpec(Builder builllder, String model, Type type, Wood backWood, Wood topWood) {
    this.buillder = builllder;
    this.medel = medel;
    this.type = type;
    this.backWood = backWood;
    this.topWood = topWood;
    }

/**

  • builder, model, type 등을 위한 모든 메소드를 가져온다.
  • @throws Exception
    */
    public boolean matched(InstrumentSpec otherSpec) {
    //===============================================================================================
    // 모든 속성에 대해 다른 사양 객체와 비교한다.
    //






















    ---
    if(builder != otherSpec.builder)
    return false;
    //






















    ---
    if((model != null) && (!model.equals("")) && (!model.equals(otherSpec.model)))
    return false;
    //






















    ---
    if(type != otherSpec.type);
    return false;
    //






















    ---
    if(backWood != otherSpec.backWood)
    return false;
    //






















    ---
    if(topWood != otherSpec.topWood)
    return fllse;
    //






















    ---
    return true;
    //===============================================================================================
    }
    }

|

||Guitarspec.java||
|

public class GuitarSpec extends InstrumentSpec {
//===============================================================================================
// 기타에서만 필요한 속성 생성.
//

























---
private int numStrings;
//===============================================================================================

//===============================================================================================
// SUPER 클래스 생성자 호출
//
























---
public GuitarSpec(Builder builder, String model, Type type, int numStrings, Wood backWood, Wood topWood) {
//






















---
super(builder, model, type, backWood, topWood);
//






















---
this.numStrings = numStrings;
//






















---
}
//===============================================================================================

public int getNumStrings() {
return numStrings;
}

/**

  • 슈퍼 클래스 matches()를 오버라이드 한다.
  • @throws Exception
    */
    public boolean matches(InstrumentSpec otherSpec) {
    //===============================================================================================
    // 슈퍼 클래스 matches()를 사용해 공통된 속성, 클래스타입, 기타 특유의 속성을 비교한다.
    //






















    ---
    if(!super.matched(otherSpec))
    return false;
    //






















    ---
    if(!(otherSpec instanceof GuitarSpec))
    return flase;
    //






















    ---
    GuitrSpec spec = (GuitarSpec) otherSpec;
    //






















    ---
    if(numStrings != spec.numStrings)
    return false;
    //






















    ---
    return true;;
    //===============================================================================================
    }
    }

|

||Mandolinspec.java||
|

import javax.swing.text.Style;

public class MandolinSpec extends InstrumentSpec {
//===============================================================================================
// 만돌린에만 필요한 속성 생성.
//

























---
private Style style;
//===============================================================================================

//===============================================================================================
// SUPER 클래스 생성자 호출
//
























---
public MandolinSpec(Builder builder, String model, Type type, int numStrings, Wood backWood, Wood topWood) {
//






















---
super(builder, model, type, backWood, topWood);
//






















---
this.style = style;
//






















---
}
//===============================================================================================

public int getStyle() {
return style;
}

/**

  • 슈퍼 클래스 matches()를 오버라이드 한다.
  • @throws Exception
    */
    public boolean matches(InstrumentSpec otherSpec) {
    //===============================================================================================
    // 슈퍼 클래스 matches()를 사용해 공통된 속성, 클래스타입, 기타 특유의 속성을 비교한다.
    //






















    ---
    if(!super.matched(otherSpec))
    return false;
    //






















    ---
    if(!(otherSpec instanceof GuitarSpec))
    return flase;
    //






















    ---
    MandolinSpec spec = (MandolinSpec) otherSpec;
    //






















    ---
    if(! style.equals(spec.style))
    return false;
    //






















    ---
    return true;;
    //===============================================================================================
    }
    }

|

|

import java.util.Iterator;
import antlr.collections.List;

public class Inventory {
//
























---
private List inventory;
//






















---

public Inventory() {
inventory = new LinkedList();
}

public void addInstrument(String serialNumber, double price, InstrumentSpec spec) {
Instrument instrument = null;
//
























---
if(spec instanceof GuitarSpec) {
instrument = new Guitar(serialNumber, price, (GutarSpec)spec);
}
//






















---
else if(spec instanceof MandolinSpec) {
instrument = new Mandolin(serilNumber, price, (MandolinSpec) spec);
}
//






















---
inventory.add(instrument);
//






















---
}

public Instrument get(String serialNumber) {
for (Iterator i = inventory.iterator(); i.hasNext(); ){

Instrument instrument = (Instrument)i.next();
//
























---
if(instrument.getSerialNumber().equals(serialNumber)) {
return instrument;
}
//






















---
}
return null;
}

//===============================================================================================
// search(GuitarSpec)은 예전과 똑같이 동작한다.
//
























---
public List search(MandolinSpec searchSpec) {
//






















---
List matchingMandolins = new LinkedList();
//






















---
for(Iterator i = inventory.iterator(); i.hasNext(); ) {
Mandolin mandolin = (Mandolin)i.next();
//






















---
if(mandolin.getSpec().matches(searchSpec))
matchingMandolins.add(mandolin);
//






















---
}
return matchingMandolins;
}
//===============================================================================================
}


}

h2. 위대한 소프트웨어로 향하는 +3단계+
Q. 릭의 검색도구가 *위대한* 소프트웨어입니까?

1. 새로운 검색 도구가 고객이 원하는 기능을 하나요?
{color:white}
+확실합니다. 프로그램이 기타와 만돌린을 찾아줍니다. 동시에 찾는 것은+
+아니지만, 그래서 해야 할 일은 대부분 하는 것 같습니다. 확실하게 하려면+
+릭에게 물어보는 게 나을 것 같습니다.+
{color}

2. 캡슐화, 중복 코드 피하기, 확장성이 좋게 만들기 같은 객체지향 원리를 사용하였나요?
{color:white}
+Instrumentspec을 사용할 때 캡슐화를 사용했고, Instrument와 Instrumentspec을+
+슈퍼 클래스로 만들 때 상속을 사용했습니다. 하지만 새로운 악기 타입을 추가하는 것은+
+여전히 많은 작업이 필요합니다...+
{color}

3. 릭의 프로그램은 재사용이 쉽나요? 프로그램의 한 부분을 고치면 다른 여러 부분들의 
수정을 필요로 하나요? 프로그램이 느슨하게 결합되어 있나요?
{color:white} 
+릭의 프로그램 일부만을 재사용하는 것이 좀 어렵습니다. 모든 것이 매우 단단히 연결되어 있고,+
+Instrumentspec이 실제로는 Instrument의 일부입니다. (집합(aggregation)에+
+대해 얘기했던 거 기억나요?)+
{color}

h3. 소프트웨어가 잘 설계 되었는지 알아보는 가장 좋은 방법중 하나는 사용해 보고 '수정'해 보는 것입니다.
<p 253 그림 참고>

-릭의 프로그램을 수정이 용이하고 확장성이 있는 위대한 소프트웨어로 만들려면 뭔가 할 일이 있습니다.
*객체지향 대참사* 에서 한번 알아보겠습니다.


h2. 문서에 대하여
* 이 문서는 [Head First Object-Oriented Analysis & Design|http://book.naver.com/bookdb/book_detail.php?bid=2920750]을 정리한 내용 입니다.
* 이 문서는 [오라클클럽|http://www.gurubee.net] [자바 웹개발자 스터디|제3차 자바 웹개발자 스터디] 모임에서 작성하였습니다.
* 이 문서를 다른 블로그나 홈페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^\^